/*
    Copyright 2006-2011 Patrik Jonsson, sunrise@familjenjonsson.org

    This file is part of Sunrise.

    Sunrise is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    Sunrise is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Sunrise.  If not, see <http://www.gnu.org/licenses/>.

*/

/// \file
/// Declaration of the full_sed_emergence class.

#ifndef __full_sed_emergence__
#define __full_sed_emergence__

#include "emergence.h"
#include "biniostream.h"

namespace mcrx {
  class full_sed_emergence;
}

class binifstream;

/** Emergence class for full-SED, no-scattering runs. This class is
    used when the dust-free images are generated.  Since there is no
    scattering, we can transport the entire SED at once.  Thus, this
    class is a derivation of the emergence template, with every pixel
    being a one-dimensional array. */
class mcrx::full_sed_emergence: public emergence<array_1> {
private:
  class thread;
  void serial_write_images (CCfits::FITS& file, T_float normalization,
			    const T_unit_map& units, 
			    const std::string& hduname,
			    bool do_compress);
  void parallel_write_images (CCfits::FITS& file, T_float normalization,
			    const T_unit_map& units, 
			    const std::string& hduname);
  
  T_float write_units (CCfits::ExtHDU&, T_camera&, 
		       const T_unit_map&, T_float);

  void mpi_collect_images();

public:
  /// Constructor just forwards to the emergence constructor.
  full_sed_emergence(int nt, int np, T_float cd, T_float fov, 
		     unsigned int size, bool exclude_south_pole = false,
		     const vec3d& translate_origin=vec3d(0,0,0),
		     const std::string& type=rectilinear_projection::typestring_) :
    emergence<array_1> (nt, np, cd, fov, size, exclude_south_pole, 
			translate_origin, type) {};

  /// Constructor just forwards to the emergence constructor.
  full_sed_emergence
  (const std::vector<std::pair<T_float, T_float> >& cam_pos,
   T_float cd, T_float fov, unsigned int size, const vec3d& translate_origin=vec3d(0,0,0),
   const std::string& type=rectilinear_projection::typestring_) :
    emergence<array_1> (cam_pos, cd, fov, size, translate_origin, type) {};

  /// Constructor just forwards to the emergence constructor.
  full_sed_emergence (const std::vector<vec3d>& cam_pos, 
		      const std::vector<vec3d>& cam_dir,
		      const std::vector<vec3d>& cam_up,
		      const std::vector<T_float>& fov, 
		      unsigned int size,
		      const vec3d& translate_origin=vec3d(0,0,0),
		      const std::string& type=rectilinear_projection::typestring_) :
    emergence<array_1> (cam_pos, cam_dir, cam_up, fov, size, 
			translate_origin, type) {};

  full_sed_emergence (const CCfits::FITS& file);
  full_sed_emergence (const std::vector<const T_camera*>& cams) :
    emergence<array_1> (cams) {};

  void write_images (CCfits::FITS& file, T_float normalization,
		     const T_unit_map& units, const std::string& hduname, 
		     bool do_compress, bool parallel_compress);
  void load_images (const CCfits::FITS& file, const std::string& hduname);
  void write_dump (binofstream&) const;
  bool load_dump (binifstream&);
  void write_dump (const std::string& file_name) const {
    binofstream file (file_name.c_str());
    write_dump (file);}; 
  bool load_dump (const std::string& file_name) {
    binifstream file (file_name.c_str());
    return load_dump (file);};

};

/** Used to simultaneously write the camera arrays as compressed FITS
    extensions.  Because cfitsio is not thread safe, the method used
    is to spawn a thread for each camera and then execute an
    independent process (in cmprauxfits.cc) to write a temporary
    file. These temporary files are then copied into the desired
    output file.  This class is the Boost thread class for these
    threads. */
class mcrx::full_sed_emergence::thread {
public:
  const int camera_number;
  const std::string file_name;
  array_3& image;
  const T_float normalization;
  int status; ///< Exit status

  thread (int c, const std::string& f, array_3& im, T_float n):
    camera_number (c), file_name (f), image (im), normalization (n),
    status(0) {};
  void operator () ();
};

#endif



